package com.tjetc.listerner;

import cn.hutool.core.util.SerializeUtil;
import cn.hutool.db.sql.Order;
import cn.hutool.json.JSONUtil;
import com.rabbitmq.client.Channel;
import com.tjetc.dao.OrdersMapper;
import com.tjetc.dao.PassMapper;
import com.tjetc.dao.TicketMapper;
import com.tjetc.domain.dto.OrderDTO;
import com.tjetc.domain.enums.OrderStatus;
import com.tjetc.domain.po.Orders;
import com.tjetc.domain.po.Ticket;
import com.tjetc.service.IOrdersService;
import com.tjetc.utils.MultiDelayMessage;
import com.tjetc.utils.PoToVoUtil;
import com.tjetc.utils.RedisIdWorker;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;

@Component
@Slf4j
public class OrderListener {

    public static final String EXCHANGE_DIRECT = "exchange.direct.order";
    public static final String ROUTING_KEY = "order";
    public static final String QUEUE_NAME = "queue.order";


    @Autowired
    private IOrdersService ordersService;

    @Autowired
    private PoToVoUtil poToVoUtil;


    @Autowired
    private RedisIdWorker redisIdWorker;


    @Autowired
    private OrdersMapper ordersMapper;


    @Autowired
    private PassMapper passMapper;

    @Autowired
    private TicketMapper ticketMapper;

    //  @RabbitListener(queues = QUEUE_NAME)
  /*  @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = QUEUE_NAME, durable = "true"),
            exchange = @Exchange(value = EXCHANGE_DIRECT, delayed = "true"),
            key = {ROUTING_KEY}
    ))
    public void process(MultiDelayMessage<Long> msg, Message message, Channel channel) throws IOException {
        long deliverTag = message.getMessageProperties().getDeliveryTag();
        try {
            //查询订单状态
            Orders order = ordersService.selectByOrderNo(msg.getData().toString());
            //判断是否已支付
            if (order == null || order.getStatus() == OrderStatus.getOrderStatus("已支付").getNum()) {
                *//*订单不存在 或者 订单已经支付了  不用取消了*//*
                channel.basicAck(deliverTag, false);
                return;
            }
            //未支付 获取下一次延迟时间
            if (msg.hasNextDelay()) {
                //存在，重发
                Long nextDelay = msg.removeNextDelay();
            } else {
                //不存在，半个小时了
                //取消订单,恢复库存,删票
                ordersService.cancelOrder(poToVoUtil.toOrderVo(order));
            }
            channel.basicAck(deliverTag, false);
        } catch (Exception e) {
            Boolean redeliver = message.getMessageProperties().getRedelivered();  //true 就是已经投递过一次了， false是第一次投递失败
            if (redeliver) {
                channel.basicNack(deliverTag, false, false);  //不给机会了
            } else {
                //第一次出异常，再试一次
                channel.basicNack(deliverTag, false, true);
            }
            throw new RuntimeException(e);
        }


    }*/

    @RabbitListener(queues = "dlx.queue")
    public void DelayOrder(String msg, Message message, Channel channel) throws IOException {
        long deliverTag = message.getMessageProperties().getDeliveryTag();
        try {

            var order = ordersService.selectByOrderNo(msg);
            if (order == null || order.getStatus() == OrderStatus.getOrderStatus("已支付").getNum()) {
                return;
            }
            ordersService.cancelOrder(poToVoUtil.toOrderVo(order));
            channel.basicAck(deliverTag, false);

        } catch (Exception e) {
            boolean redelivered = message.getMessageProperties().getRedelivered();

            if (redelivered) {
                channel.basicNack(deliverTag, false, false);
            }
            channel.basicNack(deliverTag, false, true);
            log.info("消费失败:{}", msg);
        }
    }


    @RabbitListener(queues = QUEUE_NAME)
    public void PeakCut(byte[] msg, Message message, Channel channel) throws IOException {
        long deliverTag = message.getMessageProperties().getDeliveryTag();
        try {
            OrderDTO orderDTO = SerializeUtil.deserialize(msg);
            orderDTO.setStatus(OrderStatus.getOrderStatus("未支付").getNum());
            orderDTO.setCreateTime(LocalDateTime.now());
            ordersMapper.insertOrders(orderDTO);
            //*扣减缓存座位数量*//*
            //stringRedisTemplate.opsForValue().set("pass:1", String.valueOf(count - orderDTO.getNum()));
            //扣减数据库座位数量
            passMapper.reduceCount(orderDTO.getNum(), orderDTO.getPassId());
            //添加演唱会票
            for (Integer i = 0; i < orderDTO.getNum(); i++) {
                ticketMapper.add(new Ticket(orderDTO.getPassId(), orderDTO.getId()));
            }

        } catch (Exception e) {
            boolean redelivered =  message.getMessageProperties().getRedelivered();

            if (redelivered){
                channel.basicNack(deliverTag,false,false);
            }
            channel.basicNack(deliverTag,false,true);
            log.info("消费失败:{}",msg);
        }
    }



}





